package io.kiki.sba.registry.server.clientInterface.push;

import io.kiki.sba.registry.net.NetUtil;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.HashSet;
import java.util.Set;


public class PushEfficiencyImproveConfig {

    public static final int DEFAULT_CHANGE_TASK_WAITING_MILLIS = 100;
    public static final int DEFAULT_PUSH_TASK_WAITING_MILLIS = 200;
    public static final int DEFAULT_REG_WORK_WAITING_MILLIS = 200;
    public static final String CURRENT_DATA_CENTER_ALL_ZONE = "ALL_ZONE";
    public static final String ALL_APP = "ALL_APP";

    /**
     * 三板斧 配置 当前IP
     */
    private static String CURRENT_IP = NetUtil.getLocalAddress().getHostAddress();
    public int DEFAULT_CHANGE_DEBOUNCING_MILLIS = 1000;
    public int DEFAULT_CHANGE_DEBOUNCING_MAX_MILLIS = 3000;
    public int DEFAULT_PUSH_TASK_DEBOUNCING_MILLIS = 500;
    /**
     * 三板斧配置 当前Zone
     */
    private String CURRENT_ZONE;
    /**
     * session 收到 data 数据变更推送，创建 changeTask, delay changeDebouncingMillis 时间处理，避免数据连续变化触发大量推送, 默认
     * 1000ms
     */
    private int changeDebouncingMillis = DEFAULT_CHANGE_DEBOUNCING_MILLIS;
    /**
     * session 收到 data 数据变更推送，创建 changeTask, delay changeDebouncingMillis 时间处理时，设置
     * changeDebouncingMaxMillis，避免连续相同的任务一直刷新，使得 changeTask 饥饿得不到处理, 默认 3000ms
     */
    private int changeDebouncingMaxMillis = DEFAULT_CHANGE_DEBOUNCING_MAX_MILLIS;
    /**
     * session 异步处理 changeTask 的 Looper 间隔时间, 默认 100ms
     */
    private int changeTaskWaitingMillis = DEFAULT_CHANGE_TASK_WAITING_MILLIS;
    /**
     * session 异步处理 pushTask 的 Looper 间隔时间, 默认 200ms
     */
    private int pushTaskWaitingMillis = DEFAULT_PUSH_TASK_WAITING_MILLIS;
    /**
     * session 处理 pushTask delay pushTaskDebouncingMillis 时间处理，可以合并相同的推送任务，避免数据连续变化触发大量推送, 默认500ms
     */
    private int pushTaskDebouncingMillis = DEFAULT_PUSH_TASK_DEBOUNCING_MILLIS;

    /**
     * Sub 请求的 BufferWorker Loop wait 时间, 默认 200ms
     */
    private int regWorkWaitingMillis = DEFAULT_REG_WORK_WAITING_MILLIS;

    /**
     * 三板斧配置 配置在 Ip 集合 的 Session 机器生效
     */
    private Set<String> ipSet = new HashSet<>();

    /**
     * 三板斧配置 配置在 Zone 集合 的 Session 机器生效, 要求大写
     */
    private Set<String> zoneSet = new HashSet<>();

    /**
     * 三板斧配置 支持 按订阅方应用 设置 时间
     */
    private Set<String> subAppSet = new HashSet<>();
    /**
     * 三板斧配置 支持 按订阅方应用 设置 pushTask wake 默认false
     */
    private boolean pushTaskWake = false;
    /**
     * 三板斧配置 支持 按订阅方应用 设置 regWorkTask wake 默认 reg wakeup true
     */
    private boolean regWorkWake = true;

    /**
     * session 处理 pushTask delay pushTaskDebouncingMillis 时间处理，可以合并相同的推送任务，避免数据连续变化触发大量推送, 默认500ms
     */
    private int sbfAppPushTaskDebouncingMillis = DEFAULT_PUSH_TASK_DEBOUNCING_MILLIS;

    public PushEfficiencyImproveConfig() {
    }

    /**
     * 判断是否满足 三板斧灰度条件
     */
    public boolean inIpZoneSBF() {
        if (CollectionUtils.isNotEmpty(zoneSet) && zoneSet.contains(CURRENT_DATA_CENTER_ALL_ZONE)) {
            return true;
        }
        if (CollectionUtils.isNotEmpty(zoneSet) && zoneSet.contains(CURRENT_ZONE)) {
            return true;
        }
        if (CollectionUtils.isNotEmpty(ipSet) && ipSet.contains(CURRENT_IP)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否满足 三板斧灰度条件
     */
    public boolean inAppSBF(String appName) {
        if (CollectionUtils.isNotEmpty(subAppSet) && subAppSet.contains(ALL_APP)) {
            return true;
        }
        if (CollectionUtils.isNotEmpty(subAppSet) && subAppSet.contains(appName)) {
            return true;
        }
        return false;
    }

    public int getChangeDebouncingMillis() {
        if (inIpZoneSBF()) {
            return changeDebouncingMillis;
        }
        return DEFAULT_CHANGE_DEBOUNCING_MILLIS;
    }

    public int getChangeDebouncingMaxMillis() {
        if (inIpZoneSBF()) {
            return changeDebouncingMaxMillis;
        }
        return DEFAULT_CHANGE_DEBOUNCING_MAX_MILLIS;
    }

    public int getChangeTaskWaitingMillis() {
        if (inIpZoneSBF()) {
            return changeTaskWaitingMillis;
        }
        return DEFAULT_CHANGE_TASK_WAITING_MILLIS;
    }

    public int getPushTaskWaitingMillis() {
        if (inIpZoneSBF()) {
            return pushTaskWaitingMillis;
        }
        return DEFAULT_PUSH_TASK_WAITING_MILLIS;
    }

    public int getPushTaskDebouncingMillis() {
        if (inIpZoneSBF()) {
            return pushTaskDebouncingMillis;
        }
        return DEFAULT_PUSH_TASK_DEBOUNCING_MILLIS;
    }


    public int getRegWorkWaitingMillis() {
        if (inIpZoneSBF()) {
            return regWorkWaitingMillis;
        }
        return DEFAULT_REG_WORK_WAITING_MILLIS;
    }


    public int fetchSbfAppPushTaskDebouncingMillis(String appName) {
        if (inAppSBF(appName)) {
            return sbfAppPushTaskDebouncingMillis;
        }
        return getPushTaskDebouncingMillis();
    }

    public boolean fetchPushTaskWake(String appName) {
        if (inAppSBF(appName)) {
            return pushTaskWake;
        }
        return false;
    }

    public boolean fetchRegWorkWake(String appName) {
        if (inAppSBF(appName)) {
            return regWorkWake;
        }
        return true;
    }


    public void setSessionServerConfig(Config config) {
        if (null != config && StringUtils.isNotBlank(config.getSessionServerRegion())) {
            this.CURRENT_ZONE = config.getSessionServerRegion().toUpperCase();
            this.DEFAULT_CHANGE_DEBOUNCING_MILLIS = config.getDataChangeDebouncingMillis();
            this.DEFAULT_CHANGE_DEBOUNCING_MAX_MILLIS = config.getDataChangeMaxDebouncingMillis();
            this.DEFAULT_PUSH_TASK_DEBOUNCING_MILLIS = config.getPushDataTaskDebouncingMillis();
        }
    }

    public boolean validate() {
        if (pushTaskWaitingMillis <= 0 || changeTaskWaitingMillis <= 0) {
            return false;
        }
        return true;
    }


}
